package com.multimedia.scala.euler

import scala.collection.mutable.ListBuffer
import scala.concurrent.MailBox
import scala.annotation.tailrec
import scala.actors._
object Asd76 {
    def main(args : Array[String]) : Unit = {
        var aiPn = (0 to 100).map(x=>0).toBuffer
        aiPn(0)=1
		def CalcPn(n: Int): Int = {
			// P(<0) = 0 by convention 
			if(n < 0) return 0
			
			// Use cached value if already calculated 
			if(aiPn(n) > 0) return aiPn(n)
			
			var Pn = 0
			val nsqrt = Math.sqrt(n).toInt
			for(k <- 1 to nsqrt) {
				// A little bit of recursion 
				val n1 = n - k * (3 * k - 1) / 2
				val n2 = n - k * (3 * k + 1) / 2
				println(n1, n2)
				
				val Pn1 = CalcPn(n1)
				val Pn2 = CalcPn(n2)
				
				// elements are alternately added and subtracted 
				if (k % 2 == 1) Pn = Pn + Pn1 + Pn2
				else Pn = Pn - Pn1 - Pn2
			}
		
			// Cache calculated valued 
			aiPn(n) = Pn
			return Pn
		}

        //println(find(100), p)
        //100 = 190569291
        println(CalcPn(100)-1)
        //val m = new Master(100)
        //m.start()
    }

    class Master(x: Int, n: Int = 4) extends Actor {
        val m = new MailBox()
        def act() {
            val slaves = (1 to n).map(y=>new Slave(x, m))
            var rez = 0
            var finish = 0
            (1 to x-1).foreach(max=>m send Count(x-max, max))
            slaves.foreach(a=>{a.start()})
            (1 to x-1).foreach(y=>
                m.receive{
                  case Finished(count) => {
                      println(y)
                      rez += count
                  }
                }
            )
            slaves.foreach(a=>m send Stop)
            println(rez)
        }
    }

    class Slave(x: Int, m: MailBox) extends Actor {
        def next(r: Int, prev: Int): Int = {
            if (r == 0) return 1
            (1 to prev).filter(_<=r).map(y=>{next(r - y, y)}).sum
        }
        def act() {
            loop{
                m receive {
                  case Count(r: Int, prev: Int) => {
		              val rez = next(r, prev)
		              //println(prev + " = " + rez)
                      m send Finished(rez)
                  }
                  case Stop => exit()
                }
            }
        }
    }

    case class Stop
    case class Count(r: Int, prev: Int)
    case class Finished(count: Int)
}
